package com.gitee.kenewstar.migration.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.kenewstar.migration.constants.Const;
import com.gitee.kenewstar.migration.entity.Lov;
import com.gitee.kenewstar.migration.entity.LovTl;
import com.gitee.kenewstar.migration.entity.LovValue;
import com.gitee.kenewstar.migration.entity.LovValueTl;
import com.gitee.kenewstar.migration.entity.LovViewHeader;
import com.gitee.kenewstar.migration.entity.LovViewHeaderTl;
import com.gitee.kenewstar.migration.entity.LovViewLine;
import com.gitee.kenewstar.migration.entity.LovViewLineTl;
import com.gitee.kenewstar.migration.mapper.LovMapper;
import com.gitee.kenewstar.migration.mapper.LovTlMapper;
import com.gitee.kenewstar.migration.mapper.LovValueMapper;
import com.gitee.kenewstar.migration.mapper.LovValueTlMapper;
import com.gitee.kenewstar.migration.mapper.LovViewHeaderMapper;
import com.gitee.kenewstar.migration.mapper.LovViewHeaderTlMapper;
import com.gitee.kenewstar.migration.mapper.LovViewLineMapper;
import com.gitee.kenewstar.migration.mapper.LovViewLineTlMapper;
import com.gitee.kenewstar.migration.service.LovService;
import com.gitee.kenewstar.migration.util.Util;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author kenewstar
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LovServiceImpl implements LovService {

    private final LovTlMapper lovTlMapper;
    private final LovMapper lovMapper;
    private final LovValueMapper lovValueMapper;
    private final LovValueTlMapper lovValueTlMapper;
    private final LovViewHeaderMapper lovViewHeaderMapper;
    private final LovViewHeaderTlMapper lovViewHeaderTlMapper;
    private final LovViewLineMapper lovViewLineMapper;
    private final LovViewLineTlMapper lovViewLineTlMapper;

    @Override
    @DS("dev")
    public List<LovTl> devSelectTl(QueryWrapper<LovTl> queryWrapper) {
        return this.lovTlMapper.selectList(queryWrapper);
    }

    @Override
    @DS("dev")
    public List<Lov> devSelectLov(List<Long> lovIds) {
        if (CollUtil.isEmpty(lovIds)) {
            return Collections.emptyList();
        }
        QueryWrapper<Lov> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("lov_id", lovIds);
        return this.lovMapper.selectList(queryWrapper);
    }

    @Override
    @DS("dev")
    public List<Lov> devSelectLovList(List<Lov> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<String, String> filterMap = list.stream().collect(Collectors.toMap(x -> x.getLovCode() + "-" + x.getTenantId(), Lov::getLovCode));
        QueryWrapper<Lov> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(LOV_CODE, list.stream().map(Lov::getLovCode).collect(Collectors.toSet()));
        queryWrapper.in(Const.TENANT_ID, list.stream().map(Lov::getTenantId).collect(Collectors.toSet()));
        List<Lov> lovList = this.lovMapper.selectList(queryWrapper);
        return lovList.stream().filter(x -> Objects.nonNull(filterMap.get(x.getLovCode() + "-" + x.getTenantId()))).collect(Collectors.toList());
    }

    @Override
    @DS("dev")
    public List<Lov> devSelectLov(List<String> lovCodeList, Long tenantId) {
        if (CollUtil.isEmpty(lovCodeList)) {
            return Collections.emptyList();
        }
        QueryWrapper<Lov> wrapper = new QueryWrapper<>();
        wrapper.in(LOV_CODE, lovCodeList);
        if (Objects.nonNull(tenantId)) {
            wrapper.eq(Const.TENANT_ID, tenantId);
        }
        return this.lovMapper.selectList(wrapper);
    }

    @Override
    @DS("dev")
    public List<LovValue> devSelectLovValue(QueryWrapper<LovValue> queryWrapper) {
        return this.lovValueMapper.selectList(queryWrapper);
    }

    @Override
    @DS("dev")
    public List<LovValueTl> devSelectLovValueTl(QueryWrapper<LovValueTl> queryWrapper) {
        return this.lovValueTlMapper.selectList(queryWrapper);
    }


    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovTl(List<LovTl> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovTlMapper::insert);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLov(List<Lov> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovMapper::insert);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovValue(List<LovValue> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovValueMapper::insert);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovValueTl(List<LovValueTl> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovValueTlMapper::insert);
    }

    @Override
    @DS("uat")
    public List<Lov> uatSelectLov(List<String> lovCodeList) {
        if (CollUtil.isEmpty(lovCodeList)) {
            return Collections.emptyList();
        }
        QueryWrapper<Lov> wrapper = new QueryWrapper<>();
        wrapper.in(LOV_CODE, lovCodeList);
        return this.lovMapper.selectList(wrapper);
    }

    @Override
    @DS("dev")
    public List<LovViewHeader> devSelectLovHeader(List<String> lovViewCodeList, Long tenantId) {
        if (CollUtil.isEmpty(lovViewCodeList)) {
            return Collections.emptyList();
        }
        QueryWrapper<LovViewHeader> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(VIEW_CODE, lovViewCodeList);
        if (Objects.nonNull(tenantId)) {
            queryWrapper.eq(Const.TENANT_ID, tenantId);
        }
        return this.lovViewHeaderMapper.selectList(queryWrapper);
    }

    @Override
    @DS("dev")
    public List<LovViewHeader> devSelectLovHeaderList(List<LovViewHeader> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<String, String> filterMap = list.stream().collect(Collectors.toMap(x -> x.getViewCode() + "-" + x.getTenantId(), LovViewHeader::getViewCode));
        QueryWrapper<LovViewHeader> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(VIEW_CODE, list.stream().map(LovViewHeader::getViewCode).collect(Collectors.toSet()));
        queryWrapper.in(Const.TENANT_ID, list.stream().map(LovViewHeader::getTenantId).collect(Collectors.toSet()));
        List<LovViewHeader> lovList = this.lovViewHeaderMapper.selectList(queryWrapper);
        return lovList.stream().filter(x -> Objects.nonNull(filterMap.get(x.getViewCode() + "-" + x.getTenantId()))).collect(Collectors.toList());
    }

    @Override
    @DS("dev")
    public List<LovViewHeaderTl> devSelectLovHeaderTl(QueryWrapper<LovViewHeaderTl> queryWrapper) {
        return this.lovViewHeaderTlMapper.selectList(queryWrapper);
    }

    @Override
    @DS("dev")
    public List<LovViewLine> devSelectLovLine(QueryWrapper<LovViewLine> queryWrapper) {
        return this.lovViewLineMapper.selectList(queryWrapper);
    }

    @Override
    @DS("dev")
    public List<LovViewLineTl> devSelectLovLineTl(QueryWrapper<LovViewLineTl> queryWrapper) {
        return this.lovViewLineTlMapper.selectList(queryWrapper);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovHeader(List<LovViewHeader> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovViewHeaderMapper::insert);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovHeaderTl(List<LovViewHeaderTl> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovViewHeaderTlMapper::insert);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovLine(List<LovViewLine> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovViewLineMapper::insert);
    }

    @Override
    @DS("uat")
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertLovLineTl(List<LovViewLineTl> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.lovViewLineTlMapper::insert);
    }
}
